package com.robot.console.client;

import com.go.transport.codec.XmlSocketNettyDecoder;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelUpstreamHandler;
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.frame.LengthFieldBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.LengthFieldPrepender;
import org.jboss.netty.handler.execution.ExecutionHandler;
import org.jboss.netty.handler.stream.ChunkedWriteHandler;

import java.util.concurrent.ExecutorService;

import static org.jboss.netty.channel.Channels.pipeline;

public class ClientPipelineFactory implements ChannelPipelineFactory
{
	private final static int LENGTH_FIELD_OFFSET = 0;
	private final static int LENGTH_FIELD_SIZE = 4;
	private final static int MAX_FRAME_LENGTH = 102400;

	public static int getLengthFieldOffset()
	{
		return LENGTH_FIELD_OFFSET;
	}

	public static int getLengthFieldSize()
	{
		return LENGTH_FIELD_SIZE;
	}

	private final ExecutorService executor;

	private final ChannelUpstreamHandler handler;

	public ClientPipelineFactory(ExecutorService executor, ChannelUpstreamHandler handler)
	{
		this.executor = executor;
		this.handler = handler;
	}

	@Override
	public ChannelPipeline getPipeline() throws Exception
	{
		ChannelPipeline pipeline = pipeline();

		if (Client.zip)
		{
			pipeline.addLast("framedecoder", new LengthFieldBasedFrameDecoder(MAX_FRAME_LENGTH, LENGTH_FIELD_OFFSET,
					LENGTH_FIELD_SIZE, 0, LENGTH_FIELD_SIZE));

			pipeline.addLast("zlibDecoder", new ZlibDecoder());
			pipeline.addLast("xmlsocketdecoder", new XmlSocketNettyDecoder());

			pipeline.addLast("frameEncoder", new LengthFieldPrepender(LENGTH_FIELD_SIZE));
			pipeline.addLast("zlibEncoder", new ZlibEncoder());
		}
		else
		{
			pipeline.addLast("framedecoder",
					new DelimiterBasedFrameDecoder(MAX_FRAME_LENGTH, Delimiters.nulDelimiter()));
			pipeline.addLast("xmlsocketdecoder", new XmlSocketNettyDecoder());
		}

		pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
		if (this.executor != null)
		{
			pipeline.addLast("executor", new ExecutionHandler(this.executor));
		}
		pipeline.addLast("handler", this.handler);
		return pipeline;
	}

}
